﻿using System;
using System.Collections.Generic;
using Microsoft.SharePoint;
using IBS.Webparts.PostIt.Code.Interfaces;
using IBS.Webparts.PostIt.Code.Models;

namespace IBS.Webparts.PostIt.Code.Repositories
{
    class PostItNoteRepository : IPostItNoteRepository
    {
        private const string DefaultList = "PostItList";
        private const string DefaultTitleField = "Title";
        private const string DefaultStartDateField = "StartDate";
        private const string DefaultEndDateField = "EndDate";


        /// <summary>
        /// Retrieve the List of Active Post-It Notes
        /// </summary>
        public List<PostItItem> GetActiveNotes(Guid listId, string titleField, string startDateField, string endDateField)
        {
            var notes = new List<PostItItem>();
            var titleFieldToUse = titleField;
            var startDateFieldToUse = startDateField;
            var endDateFieldToUse = endDateField;

            // Validate input
            if (string.IsNullOrEmpty(startDateField) || string.IsNullOrEmpty(endDateField))
                return notes;


            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                using (var site = new SPSite(SPContext.Current.Site.ID))
                {
                    using (var web = site.OpenWeb(SPContext.Current.Web.ID))
                    {
                        SPList list;

                        try
                        {
                            list = web.Lists.GetList(listId, false);
                        }
                        catch (Exception x)
                        {
                            // If the configured list does not exist, use the default list
                            list = web.Lists.TryGetList(DefaultList);
                            titleFieldToUse = DefaultTitleField;
                            startDateFieldToUse = DefaultStartDateField;
                            endDateFieldToUse = DefaultEndDateField;
                        }

                        var allItems = list.Items;
                        var now = DateTime.Now;

                        // If any of the fields do not match up with the table,
                        // then exit gracefully.
                        if (!list.Fields.ContainsField(titleFieldToUse) ||
                            !list.Fields.ContainsField(startDateFieldToUse) ||
                            !list.Fields.ContainsField(endDateFieldToUse)) return;


                        foreach (SPListItem item in allItems)
                        {
                            var title = item[titleFieldToUse].ToString();
                            var startDate = Convert.ToDateTime(item[startDateFieldToUse]);
                            var endDate = Convert.ToDateTime(item[endDateFieldToUse]);

                            // Filter messages outside of valid timeframe
                            if (startDate < now && endDate > now)
                            {
                                notes.Add(new PostItItem
                                {
                                    Id = item.ID,
                                    Note = title,
                                    StartDate = startDate,
                                    EndDate = endDate
                                });
                            }
                        }
                    }
                }
            });

            return notes;
        }


        /// <summary>
        /// Retrieve the ListId for the specified list
        /// </summary>
        /// <returns>List Id</returns>
        public Guid GetListId(string listName)
        {
            Guid id = new Guid();
            SPList list = null;

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(SPContext.Current.Site.ID))
                {
                    using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ID))
                    {
                        list = web.Lists.TryGetList(listName);
                        if (list != null)
                            id = list.ID;
                    }
                }
            });

            return id;
        }


        /// <summary>
        /// Retrieve the list of SharePoint Lists
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, string> GetListOptions()
        {
            var lists = new Dictionary<string, string>();

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(SPContext.Current.Site.ID))
                {
                    using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ID))
                    {
                        try
                        {
                            SPListCollection allLists = web.Lists;

                            // Handle gracefully if no list was returned
                            if (allLists != null)
                            {
                                foreach (SPList list in allLists)
                                {
                                    if (list.Hidden == false)
                                    {
                                        lists.Add(list.ID.ToString(), list.Title);
                                    }
                                }
                            }
                        }
                        catch (SPException x)
                        {
                            // If the list does not exist, we will handle silently for now
                        }
                    }
                }
            });

            return lists;
        }


        /// <summary>
        /// Retrieve the list of fields which can be used as the Title for the PostIt Webpart from the specified List
        /// </summary>
        /// <param name="id">List ID</param>
        /// <returns>List of Fields</returns>
        public Dictionary<string, string> GetTitleFieldOptions(Guid id)
        {
            var fields = new Dictionary<string, string>();

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(SPContext.Current.Site.ID))
                {
                    using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ID))
                    {
                        SPList list = null;

                        try
                        {
                            list = web.Lists.GetList(id, false);

                            // Handle gracefully if no list was returned
                            if (list != null)
                            {
                                foreach (SPField field in list.Fields)
                                {
                                    if (field.TypeAsString == "Text" && field.Hidden == false)
                                    {
                                        fields.Add(field.Title, field.Title);
                                    }
                                }
                            }
                        }
                        catch (SPException x)
                        {
                            // If the list does not exist, we will handle silently for now
                        }
                    }
                }
            });

            return fields;
        }


        /// <summary>
        /// Retrieve the list of DataTime fields from the specified List
        /// </summary>
        /// <param name="id">List ID</param>
        /// <returns>List of Fields</returns>
        public Dictionary<string, string> GetDateFieldOptions(Guid id)
        {
            var fields = new Dictionary<string, string>();

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(SPContext.Current.Site.ID))
                {
                    using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ID))
                    {
                        SPList list = null;

                        try
                        {
                            list = web.Lists.GetList(id, false);

                            // Handle gracefully if no list was returned
                            if (list != null)
                            {
                                foreach (SPField field in list.Fields)
                                {
                                    if (field.TypeAsString == "DateTime" && field.Hidden == false)
                                    {
                                        fields.Add(field.Title, field.Title);
                                    }
                                }
                            }
                        }
                        catch (SPException x)
                        {
                            // If the list does not exist, we will handle silently for now
                        }
                    }
                }
            });

            return fields;
        }

    }
}
